//
// Created by 田杰 on 2018/5/16.
//

#ifndef COMPILER_COMMON_H
#define COMPILER_COMMON_H

#define MAXRESERVED 21
#define MAXCONTENT 30

#include <string>
#include <list>
#include <iostream>

enum LexType {
    /* 保留字 */
            PROGRAM/*0*/,
    PROCEDURE/*1*/,
    TYPE/*2*/,
    VAR/*3*/,
    IF/*4*/,
    THEN/*5*/,
    ELSE/*6*/,
    FI/*7*/,
    WHILE/*8*/,
    DO/*9*/,
    ENDWH/*10*/,
    BEGIN/*11*/,
    END/*12*/,
    READ/*13*/,
    WRITE/*14*/,
    ARRAY/*15*/,
    OF/*16*/,
    RECORD/*17*/,
    RETURN/*18*/,
    INTEGER/*19*/,
    CHAR,//20
    /* 多字符单词符号 */
    /**
     * ID 标识符
     * INTC 无符号INT型常数
     * CHARC 字符常数
     */
            ID,
    INTC,
    CHARC,//23
    /*特殊符号 */
    /**
     * ASSIGN :=
     * EQ =
     * LT <
     * PLUS +
     * MINUS -
     * TIMES *
     * OVER /
     * LPAREN (
     * RPAREN )
     * DOT .
     * COLON :
     * SEMI ;
     * COMMA ,
     * LMIDPAREN [
     * RMIDPAREN ]
     * UNDERANGE ..
     */
            ASSIGN,
    EQ,
    LT,
    PLUS,
    MINUS,
    TIMES,
    OVER,
    LPAREN,
    RPAREN,
    DOT,
    COLON,
    SEMI,
    COMMA,
    LMIDPAREN,
    RMIDPAREN,
    UNDERANGE,
    ERROR,
    ENDOFILE,//41

    //非终极符
            Program,
    ProgramHead,
    ProgramName,
    DeclarePart,
    ProcDecpart,
    TypeDec,
    TypeDecList,//48
    TypeDecMore,
    TypeDecpart,
    TypeId,
    BaseType,
    StructureType,
    ArrayType,
    Low,
    Top,//56
    RecType,
    FieldDecList,
    FieldDecMore,
    IdList,
    IdMore,
    VarDec,
    VarDecList,//63
    VarDecMore,
    VarDecpart,
    VarIdList,
    VarIdMore,
    ProcDec,
    ProcDeclaration,
    ProcDecMore,
    ProcName,//71
    ParamList,
    ParamDecList,
    ParamMore,
    Param,
    FormList,
    FidMore,
    ProcDecPart,
    ProcBody,
    ProgramBody,//80
    StmList,
    StmMore,
    Stm,
    AssCall,
    AssignmentRest,
    ConditionalStm,
    LoopStm,
    InputStm,
    Invar,
    OutputStm,//90
    ReturnStm,
    CallStmRest,
    ActParamList,
    ActParamMore,
    RelExp,
    OtherRelE,
    Exp,
    OtherTerm,
    Term,
    OtherFactor,//100
    Factor,
    Variable,
    VariMore,
    FieldVar,
    FieldVarMore,
    CmpOp,
    AddOp,
    MultOp,
    TypeDef//109
};
static struct {
    char *str;
    LexType toke;
} reservedWords[MAXRESERVED]
        = {{ "program",   PROGRAM },
           { "type",      TYPE },
           { "var",       VAR },
           { "procedure", PROCEDURE },
           { "begin",     BEGIN },
           { "end",       END },
           { "array",     ARRAY },
           { "of",        OF },
           { "record",    RECORD },
           { "if",        IF },
           { "then",      THEN },
           { "else",      ELSE },
           { "fi",        FI },
           { "while",     WHILE },
           { "do",        DO },
           { "endwh",     ENDWH },
           { "read",      READ },
           { "write",     WRITE },
           { "return",    RETURN },
           { "integer",   INTEGER },
           { "char",      CHAR }};

enum CharType {
    /**
     * LETTER 字母
     * NUMBER 数字
     * CTEQ =
     * CTLT <
     * CTPLUS +
     * CTMINUS -
     * CTTIMES *
     * CTOVER /
     * CTLPAREN (
     * CTRPAREN )
     * CTDOT .
     * CTCOLON :
     * CTSEMI ;
     * CTCOMMA ,
     * CTLMIDPAREN [
     * CTRMIDPAREN ]
     * CTENDOFILE EOF
     * CTQUOTE '
     * OTHERS 其他字符
     */
            LETTER, NUMBER, CTEQ, CTLT, CTPLUS, CTMINUS, CTTIMES, CTOVER, CTLPAREN, CTRPAREN, CTDOT, CTCOLON, CTSEMI,
    CTCOMMA, CTLMIDPAREN, CTRMIDPAREN, CTENDOFILE, CTQUOTE, OTHERS
};

struct Token {
    int lineNumber;
    LexType lexType;
    char content[MAXCONTENT];

    Token(int tLineNum, std::string &str, LexType tLexType = ID)  //普通构造函数
    {
        lineNumber = tLineNum;
        lexType = tLexType;
        int i;
        for (i = 0; i < str.length(); ++i)
            content[i] = str[i];
        content[i] = '\0';
    }

    Token(const Token &tok)   //拷贝构造函数
    {
        lineNumber = tok.lineNumber;
        lexType = tok.lexType;
        for (int i = 0; i < MAXCONTENT; ++i)
            content[i] = tok.content[i];
    }
};

struct Char {
    int lineNumber;
    CharType charType;
    char lex;
};

#endif //COMPILER_COMMON_H
